package ids

import (
	"bytes"
	"encoding/gob"

	"gitee.com/xuender/oils/base"
)

// IDS ID列表.
type IDS map[ID]struct{}

// Intersection 交集.
func Intersection(elems ...IDS) IDS {
	switch len(elems) {
	case 0:
		return IDS{}
	case 1:
		return elems[0]
	}

	ret := IDS{}

	for elem := range elems[0] {
		has := true

		for _, is := range elems[1:] {
			if !is.Has(elem) {
				has = false

				break
			}
		}

		if has {
			ret.Add(elem)
		}
	}

	return ret
}

// NewIDS 新建IDS.
func NewIDS(elems ...ID) IDS {
	ret := IDS{}

	ret.Add(elems...)

	return ret
}

// Union 合集.
func Union(elems ...IDS) IDS {
	ret := IDS{}

	for _, e := range elems {
		ret.AddIDS(e)
	}

	return ret
}

// Unmarshal 反序列化.
func Unmarshal(bs []byte) (IDS, error) {
	var id IDS

	decoder := gob.NewDecoder(bytes.NewBuffer(bs))
	err := decoder.Decode(&id)

	return id, err
}

// Add 增加ID.
func (is IDS) Add(elems ...ID) IDS {
	for _, id := range elems {
		is[id] = base.None
	}

	return is
}

// AddBytes 追加ID.
func (is IDS) AddBytes(data ...[]byte) IDS {
	for _, bs := range data {
		is[Bytes(bs)] = base.None
	}

	return is
}

// AddIDS 增加IDS.
func (is IDS) AddIDS(elem IDS) IDS {
	for id := range elem {
		is[id] = base.None
	}

	return is
}

// All 包含全部ID.
func (is IDS) All(elems ...ID) bool {
	for _, e := range elems {
		if _, has := is[e]; !has {
			return false
		}
	}

	return true
}

// AllIDS 包含IDS全部ID.
func (is IDS) AllIDS(elem IDS) bool {
	for e := range elem {
		if _, has := is[e]; !has {
			return false
		}
	}

	return true
}

// Any 包含任意.
func (is IDS) Any(elems ...ID) bool {
	for _, e := range elems {
		if _, has := is[e]; has {
			return true
		}
	}

	return false
}

// AnyIDS 包含IDS任意ID.
func (is IDS) AnyIDS(elem IDS) bool {
	for e := range elem {
		if _, has := is[e]; has {
			return true
		}
	}

	return false
}

// Bytes IDS装换字节码.
func (is IDS) Bytes() [][]byte {
	ret := make([][]byte, len(is))
	i := -1

	for id := range is {
		i++

		ret[i] = id[:]
	}

	return ret
}

// Complement 补集.
func (is IDS) Complement(elems ...IDS) IDS {
	ret := Union(elems...)

	return ret.DelIDS(is)
}

// Del 删除ID.
func (is IDS) Del(elems ...ID) IDS {
	for _, e := range elems {
		delete(is, e)
	}

	return is
}

// DelIDS 删除IDS.
func (is IDS) DelIDS(elems IDS) IDS {
	for e := range elems {
		delete(is, e)
	}

	return is
}

// Has 包含.
func (is IDS) Has(id ID) bool {
	_, has := is[id]

	return has
}

// Marshal 序列化.
func (is IDS) Marshal() []byte {
	buffer := new(bytes.Buffer)

	encoder := gob.NewEncoder(buffer)
	_ = encoder.Encode(is)

	return buffer.Bytes()
}

// Slice 转换切片.
func (is IDS) Slice() []ID {
	ret := make([]ID, len(is))
	i := -1

	for s := range is {
		i++

		ret[i] = s
	}

	return ret
}
